'''
Created on Jun 11, 2011

@author: Igor
'''

from auctions.cr_auction import BIG_NUMBER, SMALL_NUMBER, MIN_CPC
from lib.dbobjects import Explanation, Athlete, RESULTS_DISPLAYED, \
        ATHLETES_STORED, DAILY_BUDGET

def ctr_top_athletes(stats):
    explanation = Explanation.all().get()
    explanation.title="This auction is based on product=CPC*CTR, with" + \
            " sand-bagging for new postings.  This is exactly" + \
            " what we have in production right now"
    winners = []
    new_winners = []
    athletes = Athlete.all().filter('out_of_budget =', False).fetch(ATHLETES_STORED)
    for athlete in athletes:
        if not athlete.new:
            impressions = sum(athlete.impressions)
            clicks = sum(athlete.clicks)
            product = BIG_NUMBER * athlete.cpc * clicks / impressions + athlete.cpc
            winners.append([athlete.name, product, athlete.cpc,
                            clicks, impressions, athlete.id])
        else:
            new_winners.append([athlete.name, athlete.cpc, athlete.id])
    winners.sort(key=lambda x: x[1], reverse=True)
    new_winners.sort(key=lambda x: x[1], reverse=True)
    
    ids = []
    names = []
    comments = []
    costs = []
    if len(winners) > 0:
        comments.append("The first athlete is at the top because he won" +
                        " the auction with CPC=%d and CTR=%d/%d." %
                        (winners[0][2], winners[0][3], winners[0][4]))
        # For now add cost as 0 (overwritten later)
        costs.append(0)
        names.append(winners[0][0])
        ids.append(winners[0][5])
    number_newbies = min(len(new_winners), RESULTS_DISPLAYED - len(names))
    for i in xrange(number_newbies):
        comments.append("This athlete got his spot because he is new" +
                        " and has a CPC of %d. He pays that CPC in full."
                        % new_winners[i][1])
        costs.append(new_winners[i][1])
        names.append(new_winners[i][0])
        ids.append(new_winners[i][2])
        stats.max_cpc_times += 1
    if len(names) < RESULTS_DISPLAYED:
        for i in xrange(RESULTS_DISPLAYED - len(names)):
            comments.append("This athlete got his spot because he was" +
                            " number " + str(i+2) + " in the auction with" + 
                            " CPC=%d and CTR=%d/%d." % (winners[i+1][2],
                                winners[i+1][3], winners[i+1][4]))
            costs.append(0)
            names.append(winners[i+1][0])
            ids.append(winners[i+1][5])
    names.append("None of these")
    stats.top_names = names
    
    # Calculating non-trivial costs
    if len(winners) > 0:
        if len(new_winners) >= RESULTS_DISPLAYED - 1:
            costs[0] = MIN_CPC
            comments[0] += "  He pays the min CPC of %d " % costs[0] + \
                    "for the first spot since all the other appearing athletes are new."
            stats.min_cpc_times += 1
        else:
            costs[RESULTS_DISPLAYED-1] = winners[RESULTS_DISPLAYED - 1 - len(new_winners)][2]
            comments[RESULTS_DISPLAYED-1] += "  He pays the full CPC of" + \
                    " %d for the last spot." % costs[RESULTS_DISPLAYED-1]
            stats.max_cpc_times += 1
            for i in xrange(RESULTS_DISPLAYED - 2 - len(new_winners)):
                current_index = RESULTS_DISPLAYED-2-len(new_winners)-i
                if winners[current_index][3] < SMALL_NUMBER:
                    costs[RESULTS_DISPLAYED-2-i] = 1 + winners[current_index+1][2]
                else:
                    costs[RESULTS_DISPLAYED-2-i] = 1 + \
                            (winners[current_index+1][2] *
                             winners[current_index+1][3] *
                             winners[current_index][4] /
                             winners[current_index+1][4] /
                             winners[current_index][3])
                comments[RESULTS_DISPLAYED-2-i] += "  The formula is: " + \
                        "%d*(%d/%d) / (%d/%d) + 1." % (winners[current_index+1][2],
                                                       winners[current_index+1][3],
                                                       winners[current_index+1][4],
                                                       winners[current_index][3],
                                                       winners[current_index][4])
                if costs[RESULTS_DISPLAYED-2-i] >= winners[current_index][2]:
                    costs[RESULTS_DISPLAYED-2-i] = winners[current_index][2]
                    comments[RESULTS_DISPLAYED-2-i] += "  The athlete pays his max CPC of %d" \
                            % (costs[RESULTS_DISPLAYED-2-i])
                    stats.max_cpc_times += 1
                elif costs[RESULTS_DISPLAYED-2-i] < MIN_CPC:
                    comments[RESULTS_DISPLAYED-2-i] += "  Using the formula he" + \
                            " would pay %d, but because of MIN_CPC he pays %d" \
                            % (costs[RESULTS_DISPLAYED-2-i], MIN_CPC)
                    costs[RESULTS_DISPLAYED-2-i] = MIN_CPC
                    stats.min_cpc_times += 1
                else:
                    comments[RESULTS_DISPLAYED-2-i] += "  He pays %d according to the formula." \
                            % (costs[RESULTS_DISPLAYED-2-i])
            if winners[0][3] < SMALL_NUMBER:
                costs[0] = 1 + winners[1][2]
            else:
                costs[0] = 1 + (winners[1][2] *
                                winners[1][3] *
                                winners[0][4] /
                                winners[1][4] /
                                winners[0][3])
            comments[0] += "  The formula is: " + "%d*(%d/%d) / (%d/%d) + 1." \
                    % (winners[1][2], winners[1][3], winners[1][4], winners[0][3],
                    winners[0][4])
            if costs[0] >= winners[0][2]:
                costs[0] = winners[0][2]
                comments[0] += "  He pays his max CPC of %d" % (costs[0])
                stats.max_cpc_times += 1
            elif costs[0] < MIN_CPC:
                comments[0] += "  Using the formula we would pay %d, but because of MIN_CPC he pays %d" \
                        % (costs[0], MIN_CPC)
                costs[0] = MIN_CPC
                stats.min_cpc_times += 1
            else:
                comments[0] += "  He pays %d to beat the second place by one cent and become FIRST!" \
                % (costs[0])
    stats.costs = costs
    explanation.comments = comments
    explanation.put()
    return ids
